package com.qijian.web.controller.system;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.qijian.common.annotation.Log;
import com.qijian.common.constant.Constants;
import com.qijian.common.constant.UserConstants;
import com.qijian.common.core.domain.AjaxResult;
import com.qijian.common.core.domain.UserSalaryData;
import com.qijian.common.core.domain.entity.SysMenu;
import com.qijian.common.core.domain.entity.SysUser;
import com.qijian.common.core.domain.model.LoginBody;
import com.qijian.common.core.domain.model.LoginUser;
import com.qijian.common.core.domain.model.WxLoginBody;
import com.qijian.common.core.domain.vo.SysUserVo;
import com.qijian.common.core.redis.RedisCache;
import com.qijian.common.enums.BusinessType;
import com.qijian.common.utils.SecurityUtils;
import com.qijian.common.utils.ServletUtils;
import com.qijian.common.utils.StringUtils;
import com.qijian.common.utils.ip.IpUtils;
import com.qijian.common.utils.uuid.UUID;
import com.qijian.enums.TapPermissionEnum;
import com.qijian.framework.web.service.SysLoginService;
import com.qijian.framework.web.service.SysPermissionService;
import com.qijian.framework.web.service.TokenService;
import com.qijian.system.domain.SysConfig;
import com.qijian.system.service.ISysConfigService;
import com.qijian.system.service.ISysMenuService;
import com.qijian.tool.utils.QyWxUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpOAuth2Service;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 登录验证
 *
 * @author qijian
 */
@RestController
@RequiredArgsConstructor
@Slf4j
public class SysLoginController {
    private final SysLoginService loginService;
    private final ISysMenuService menuService;
    private final SysPermissionService permissionService;
    private final TokenService tokenService;
    private final ISysConfigService configService;
    private final RedisCache redisCache;
    private final WxCpService wxCpService;



    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        LoginUser loginUser = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid(), loginBody.getClientId());
        // 生成token
        String token = tokenService.createToken(loginUser);
        SysUser user = loginUser.getUser();
        SysUserVo userVo = new SysUserVo();
        BeanUtils.copyProperties(user, userVo);
        ajax.put(Constants.TOKEN, token);
        ajax.put("user", userVo);
        return ajax;
    }

    /**
     * 无密码点击头像登录
     * @param loginBody
     * @return
     */
    @PostMapping("/noPassWordLogin")
    public AjaxResult noPassWordLogin(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        String platform = loginBody.getPlatform();
        if (!UserConstants.APP.equals(platform)) {
            throw new RuntimeException("登录失败！");
        }
        //生成令牌
        LoginUser loginUser = loginService.noPasswordLogin(loginBody.getUsername(), loginBody.getCode(),
                loginBody.getUuid(), loginBody.getClientId());
        //生成token
        String token = tokenService.createToken(loginUser);
        SysUser user = loginUser.getUser();
        SysUserVo userVo = new SysUserVo();
        BeanUtils.copyProperties(user, userVo);
        ajax.put(Constants.TOKEN, token);
        ajax.put("user", userVo);
        return ajax;
    }

    /**
     * 登录前获取所有人员
     * @param sysUser
     * @return
     */
    @GetMapping("/getAllUser")
    public AjaxResult getAllUser(SysUser sysUser) {
        List<SysUser> sysUsers = loginService.getAllUser(sysUser);
        return AjaxResult.data(sysUsers);
    }

    @GetMapping("/getAllWorkshopSection")
    public AjaxResult getAllWorkshopSection() {
        //获取所有工段
        List<String> workshopSectionList = loginService.getAllLocation();
        return AjaxResult.data(workshopSectionList);
    }

    @Log(title = "微信登录", businessType = BusinessType.GRANT)
    @PostMapping("/qyWxLogin/{code}")
    public AjaxResult qyWxLogin(@PathVariable String code) {
        // 过滤白名单
        String error = whiteListFilter();
        if (error != null) return AjaxResult.error(error);

        try {
            // 获取用户信息
            WxCpOAuth2Service oauth2Service = wxCpService.getOauth2Service();
            WxCpOauth2UserInfo userInfo = oauth2Service.getUserInfo(code);

            String userId = userInfo.getUserId();
            if (StringUtils.isEmpty(userId)) {
                return AjaxResult.error("获取企业微信用户信息失败!");
            }
            log.info("#####################################\n" + userId + "\n##############################");
            return qyWxLogin(new WxLoginBody(userId, UUID.randomUUID().toString()));

        } catch (WxErrorException e) {
            return AjaxResult.error("获取企业微信数据失败:[" + e.getMessage() + "]");
        }
    }

    @Log(title = "用户id换token", businessType = BusinessType.GRANT)
    @PostMapping("/qyWxRefresh")
    public AjaxResult qyWxRefresh(@RequestBody WxLoginBody wxLoginBody) {
        // 过滤白名单
        String error = whiteListFilter();
        if (error != null) return AjaxResult.error(error);
        return qyWxLogin(wxLoginBody);
    }

    @Nullable
    private String whiteListFilter() {
        String ipAddr = IpUtils.getIpAddr(ServletUtils.getRequest());

        String whiteList = configService.selectConfigByKey("wx-login-white-list");
        // 白名单过滤
        if (!"0.0.0.0".equals(whiteList) && !ipAddr.equals(whiteList)) {
            return "企业微信服务器[" + ipAddr + "]未加入白名单!";
        }
        return null;
    }


    /**
     * 企业微信换系统token
     *
     * @param loginBody
     * @return
     */
    public AjaxResult qyWxLogin(WxLoginBody loginBody) {

        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        LoginUser loginUser = loginService.QyWxLogin(loginBody.getWxUserId(), loginBody.getUuid());
        // 生成token
        String token = tokenService.createToken(loginUser);
        SysUser user = loginUser.getUser();
        SysUserVo userVo = new SysUserVo();
        BeanUtils.copyProperties(user, userVo);
        ajax.put(Constants.TOKEN, token);
        ajax.put("user", userVo);
        return ajax;
    }


    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo() {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        List<String> tabPermissions = CollUtil.newArrayList();
        for (String tabPermission : permissions) {
            Map<String, String> tabPermissionsMap = TapPermissionEnum.getAll();
            String tab = tabPermissionsMap.get(tabPermission);
            if (StringUtils.isNotEmpty(tab)) {
                tabPermissions.add(tab);
            }
        }
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        ajax.put("tabPermissions", tabPermissions);
        ajax.put("posts", SecurityUtils.getLoginUser().getPostName());
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters() {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    @GetMapping("getRouters/{showType}")
    public AjaxResult getRouters(SysMenu menu) {
        Long userId = SecurityUtils.getUserId();
//        if (ObjectUtils.isNull(menu.getIsLike())) {
//            if (StringUtils.isNotBlank(menu.getVersion())) {
//                menu.setVersion("NOT");
//            } else {
//                if ("app".equals(menu.getShowType())) {
//                    menu.setVersion("3.1.6");
//                }
//            }
//        }
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId, menu);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    @GetMapping("/getUserSalaryData")
    public AjaxResult getUserSalaryData(SysUser sysUser) {
        UserSalaryData userSalaryData = loginService.getUserSalaryData(sysUser);
        return AjaxResult.data(userSalaryData);
    }



}
